{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Rainy or Sunny Hidden Markov Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "authors:<br>\n",
    "Jacob Schreiber [<a href=\"mailto:jmschreiber91@gmail.com\">jmschreiber91@gmail.com</a>]<br>\n",
    "Nicholas Farn [<a href=\"mailto:nicholasfarn@gmail.com\">nicholasfarn@gmail.com</a>]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is an example of a sunny-rainy hidden markov model using yahmm. The example is drawn from the Wikipedia <a href=https://en.wikipedia.org/wiki/Hidden_Markov_model#A_concrete_example>article</a> on Hidden Markov Models describing what Bob likes to do on rainy or sunny days."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pomegranate import *\n",
    "import random\n",
    "import math\n",
    "\n",
    "random.seed(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We first create a `HiddenMarkovModel` object, and name it \"Rainy-Sunny\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = HiddenMarkovModel( name=\"Rainy-Sunny\" )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then create the two possible states of the model, \"rainy\" and \"sunny\". We make them both discrete distributions, with the possibilities of Bob either walking, shopping, or cleaning."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "rainy = State( DiscreteDistribution({ 'walk': 0.1, 'shop': 0.4, 'clean': 0.5 }), name='Rainy' )\n",
    "sunny = State( DiscreteDistribution({ 'walk': 0.6, 'shop': 0.3, 'clean': 0.1 }), name='Sunny' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then add the transitions probabilities, starting with the probability the model starts as sunny or rainy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.add_transition( model.start, rainy, 0.6 )\n",
    "model.add_transition( model.start, sunny, 0.4 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then add the transition matrix. We make sure to subtract 0.05 from each probability to add to the probability of exiting the hmm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.add_transition( rainy, rainy, 0.65 )\n",
    "model.add_transition( rainy, sunny, 0.25 )\n",
    "model.add_transition( sunny, rainy, 0.35 )\n",
    "model.add_transition( sunny, sunny, 0.55 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Last, we add transitions to mark the end of the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.add_transition( rainy, model.end, 0.1 )\n",
    "model.add_transition( sunny, model.end, 0.1 )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we \"bake\" the model, finalizing its structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.bake( verbose=True )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets check on Bob each hour and see what he is doing! In other words lets create a sequence of observations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "sequence = [ 'walk', 'shop', 'clean', 'clean', 'clean', 'walk', 'clean' ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets check the probability of observing this sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.854526990800002e-05\n"
     ]
    }
   ],
   "source": [
    "print(math.e**model.forward( sequence )[ len(sequence), model.end_index ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then the probability that Bob will be cleaning a step 3 in this sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9120990704186626\n"
     ]
    }
   ],
   "source": [
    "print(math.e**model.forward_backward( sequence )[1][ 2, model.states.index( rainy ) ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The probability of the sequence occurring given it is Sunny at step 4 in the sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0004459435000000002\n"
     ]
    }
   ],
   "source": [
    "print(math.e**model.backward( sequence )[ 3, model.states.index( sunny ) ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally the probable series of states given the above sequence."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sunny Rainy Rainy Rainy Rainy Sunny Rainy\n"
     ]
    }
   ],
   "source": [
    "print(\" \".join( state.name for i, state in model.maximum_a_posteriori( sequence )[1] ))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
